package org.ssssssss.magicboot.utils;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.druid.util.StringUtils;
import net.coobird.thumbnailator.Thumbnails;
import org.apache.poi.util.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.ssssssss.magicboot.model.Global;
import org.ssssssss.script.annotation.Comment;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

@Component
public class FileUtils {

    private static JdbcTemplate template;

    @Autowired
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
        template = jdbcTemplate;
    }

    public static Map<String, String> createFileAttr(String originalFilename){
        String ret = Global.USER_FILES_BASE_URL + DateUtil.today() + "/" + IdUtil.simpleUUID() + "/";
        String suffix = FileUtil.getSuffix(originalFilename);
        Map<String, String> map = new HashMap<>();
        map.put("ret", ret);
        map.put("filePath", ret.substring(1) + originalFilename);
        map.put("fileNames", originalFilename);
        map.put("suffix", suffix);
        return map;
    }
    /*
    保存文件
     */
    @Comment("保存文件")
    public static Map<String, String> saveFile(MultipartFile file
    ) {
        Map<String, String> fileAttr = createFileAttr(file.getOriginalFilename());
        String fileNames = fileAttr.get("fileNames");
        String ret = fileAttr.get("ret");
        String suffix = fileAttr.get("suffix");
        String realPath = Global.getUserFilesBaseDir() + ret;
        realPath = FileUtil.normalize(realPath);
        FileUtil.mkdir(realPath);
        File tempFile = new File(realPath + fileNames);
        if (!tempFile.getParentFile().exists()) {
            tempFile.getParentFile().mkdir();
        }
        try {
            if (!tempFile.exists()) {
                file.transferTo(tempFile);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
		Map<String, String> params = new HashMap<>();
		params.put("state", "SUCCESS");
		params.put("original_name", file.getOriginalFilename());
		params.put("name", file.getName());
		params.put("size", file.getSize() + "");
      	params.put("type", suffix);
      	params.put("url", fileAttr.get("filePath"));
      	return params;
	}
    /**
     * 压缩并保存文件
     * @param file
     * @param x 保留X像素宽度
     * @param y 保留Y像素宽度
     * @return
     * @throws IOException
     */
    @Comment("压缩并保存文件,X/Y为压缩后的图片长宽")
    public static Map<String, String> compressionAndSaveFile(MultipartFile file,int x,int y) throws IOException {
        Map<String, String> fileAttr = createFileAttr(file.getOriginalFilename());
        String fileNames = fileAttr.get("fileNames");
        String ret = fileAttr.get("ret");
        String suffix = fileAttr.get("suffix");
        String realPath = Global.getUserFilesBaseDir() + ret;
        realPath = FileUtil.normalize(realPath);
        FileUtil.mkdir(realPath);
        File tempFile = new File(realPath + fileNames);
        if (!tempFile.getParentFile().exists()) {
            tempFile.getParentFile().mkdir();
        }
        try {
            if (!tempFile.exists()) {
                Thumbnails.of(file.getInputStream()).size(x,y).toFile(tempFile);
//                file.transferTo(tempFile);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        Map<String, String> params = new HashMap<>();
        params.put("state", "SUCCESS");
        params.put("original_name", file.getOriginalFilename());
        params.put("name", file.getName());
        params.put("size", file.getSize() + "");
        params.put("type", suffix);
        params.put("url", fileAttr.get("filePath"));
        return params;
    }
    /*
    保存文件，同时写入sys_file表
     */
    @Comment("保存文件，同时写入sys_file表")
	public static Map<String, String> saveFileDB(MultipartFile file){
        Map<String, String> params = saveFile(file);

        String id = IdUtil.simpleUUID();
        template.update("insert into sys_file(id, url, external_type, file_name, file_size, create_by, create_date) values(?,?,?,?,?,?,?)",
                id,
                params.get("url").toString(),
                params.get("type"),
                params.get("original_name"),
                params.get("size"),
                StpUtil.isLogin() ? StpUtil.getLoginId() : "",
                new Date());

        params.put("id",id);
        return params;
    }

    /**
     * 压缩并保存文件，同时写入sys_file表
     * @param file
     * @param x 保留X像素宽度
     * @param y 保留Y像素宽度
     * @return
     * @throws IOException
     */
    @Comment("压缩并保存文件，同时写入sys_file表")
    public static Map<String, String> compressionAndSaveFileDB(MultipartFile file,int x,int y) throws IOException {
        Map<String, String> params = compressionAndSaveFile(file,x,y);

        String id = IdUtil.simpleUUID();
        template.update("insert into sys_file(id, url, external_type, file_name, file_size, create_by, create_date) values(?,?,?,?,?,?,?)",
                id,
                params.get("url").toString(),
                params.get("type"),
                params.get("original_name"),
                params.get("size"),
                StpUtil.isLogin() ? StpUtil.getLoginId() : "",
                new Date());

        params.put("id",id);
        return params;
    }


    /*
    根据id获取文件信息
     */
    @Comment("根据id获取文件信息")
    public static Map<String, Object> getFileUrlById(String fileId){
        List<Map<String, Object>> paramList = new ArrayList<>();
        paramList = template.queryForList("select id, url, external_type, file_name, file_size, create_by, create_date from sys_file where id = ?",
                fileId);
        if(paramList.size()>0) {
            return paramList.get(0);
        }else
        {
            return null;
        }

    }

    /*
    根据id下载文件
     */
    @Comment("根据id下载文件")
    public static void downloadFileById(String fileId) throws UnsupportedEncodingException {
        Map<String, Object> params = getFileUrlById(fileId);
        if(params == null){
            return;
        }

        //获取当前response
        HttpServletResponse response;
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes instanceof ServletRequestAttributes) {
            response =  ((ServletRequestAttributes) requestAttributes).getResponse();
        }
        response =  org.ssssssss.magicapi.core.context.RequestContext.getHttpServletResponse();

        String filePath = Global.getUserFilesBaseDir() + params.get("url").toString();
        File file = new File(filePath);
        String fileName = params.get("file_name").toString();

//        String fileNameURL= new String(fileName.getBytes(),"ISO8859-1");

//        String fileNameURL = URLEncoder.encode(fileName, "UTF-8");

//        fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
        fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
//        fileName = MimeUtility.encodeText(fileName, "UTF8", "B");



//        String filename = java.net.URLEncoder.encode(fileName,"UTF-8").replace("+", "%20");
//        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + filename);

//        response.setHeader("Content-Disposition", "attachment; filename="
//                + new String(fileName.getBytes("utf-8"),"ISO-8859-1"));
//        response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("utf-8"),"ISO8859-1"));
//        response.setHeader("Content-Disposition", "attachment; filename=\""+ new String(fileName.getBytes(),"ISO8859-1") +"\"");

//        response.setContentType("application/octet-stream");
//        response.setCharacterEncoding("utf-8");
//        response.setContentType("application/x-download");
//        response.addHeader("Content-Length",""+file.length());
//        response.setContentType("multipart/form-data");
//        response.setCharacterEncoding("UTF-8");
//        fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);

        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
//            response.setHeader("Content-disposition", "attachment;filename="+fileNameURL+";"+"filename*=utf-8''"+fileNameURL);
//            response.setHeader("Content-Disposition",String.format("attachment; filename=\"%s\"", fileName));
            IOUtils.copy(fis, response.getOutputStream());
            response.flushBuffer();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /*
    根据路径下载文件
     */
    @Comment("根据路径下载文件")
    public static void downloadFileByPath(String filePath) throws UnsupportedEncodingException {
        //获取当前response
        HttpServletResponse response;
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes instanceof ServletRequestAttributes) {
            response =  ((ServletRequestAttributes) requestAttributes).getResponse();
        }
        response =  org.ssssssss.magicapi.core.context.RequestContext.getHttpServletResponse();

        filePath = Global.getUserFilesBaseDir() + filePath;
        File file = new File(filePath);
        String fileName = file.getName();

        fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");

        response.setHeader("Content-Disposition", "attachment; filename=" + fileName);

        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            IOUtils.copy(fis, response.getOutputStream());
            response.flushBuffer();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 读取excel
     */
    public static List<List<Object>> readExcel(MultipartFile file) throws IOException {
        ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
        return reader.read();
    }

    /**
     * 读取excel
     */
    public static List<Map<String, Object>> readExcel(MultipartFile file, int headerRowIndex, int startRowIndex) throws IOException {
        ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
        return reader.read(headerRowIndex,startRowIndex,Integer.MAX_VALUE);
    }


    /**
     * 导出excel
     */
    public static void downloadExcel(List<Map<String, Object>> list) throws IOException {
        downloadExcel(null,list);
    }
    /**
     * 导出excel,含标题
     */
    public static void downloadExcel(String title,List<Map<String, Object>> list) throws IOException {
        HttpServletResponse response;
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes instanceof ServletRequestAttributes) {
            response =  ((ServletRequestAttributes) requestAttributes).getResponse();
        }
        response =  org.ssssssss.magicapi.core.context.RequestContext.getHttpServletResponse();

        downloadExcel(title,list,response);
    }
    /**
     * 导出excel
     */
    public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
        downloadExcel(null,list,response);
    }

    /**
     * 导出excel,含标题
     */
    public static void downloadExcel(String title,List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
        //        String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
        //        File file = new File(tempPath);
        BigExcelWriter writer = ExcelUtil.getBigWriter();
        Integer columnCount = 1;
        if(list.size()>0) {
            columnCount = list.get(0).size();
        }
        if(!StringUtils.isEmpty(title)) {
            //大标题行合并单元格
            writer.merge(list.get(0).size() - 1, title);
        }

        // 一次性写出内容，使用默认样式，强制输出标题
        writer.write(list, true);
        //SXSSFSheet sheet = (SXSSFSheet)writer.getSheet();
        //上面需要强转SXSSFSheet  不然没有trackAllColumnsForAutoSizing方法
        //sheet.trackAllColumnsForAutoSizing();
        //列宽自适应
        writer.autoSizeColumnAll();

        //response为HttpServletResponse对象
        //response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        //test.xls是弹出下载对话框的文件名，不能为中文，中文请自行编码
        response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
        ServletOutputStream out = response.getOutputStream();
        // 终止后删除临时文件
//        file.deleteOnExit();
        writer.flush(out, true);
        writer.close();
        //此处记得关闭输出Servlet流
        IoUtil.close(out);
    }
}
